#pragma once

#include <string>

#include "RelationshipType.h"
#include "RelationshipArgumentType.h"




// RelationshipEntry is the data structure containing information in the format
// RelationshipType - Argument 1 - Argument 2 - Argument Type 1 - Argument Type 2
struct RelationshipEntry {
	RelationshipType relationshipType; // The type of relationship being queried (e.g. FOLLOWS)
	std::string relationshipArguments[MAX_ARGUMENTS]; // The arguments of the relationship being queried (e.g. "a" or "2", etc.)
	RelationshipArgumentType relationshipArgumentTypes[MAX_ARGUMENTS]; // The types of the arguments of the relationship being queried (e.g. SYNONYM_ASSIGN or INTEGER, etc.)
	int numberOfArguments; // The number of arguments there are for this particular relationship clause.
	
	
	bool operator== (const RelationshipEntry &c) const {
		if (numberOfArguments!=c.numberOfArguments || relationshipType!=c.relationshipType) return false;
		for (int i = 0; i<numberOfArguments; i++) {
			if (relationshipArguments[i].compare(c.relationshipArguments[i]) !=0
			||  relationshipArgumentTypes[i] != c.relationshipArgumentTypes[i]) return false;
		}
		return true;
	}
};

namespace std {

  template <>
  struct hash<RelationshipEntry>
  {
    std::size_t operator()(const RelationshipEntry& k) const
    {
      using std::size_t;
      using std::hash;
      using std::string;

      // Compute individual hash values for first,
      // second and third and combine them using XOR
      // and bit shifting:
	  
      return ((((hash<string>()(k.relationshipArguments[0])
               ^ (hash<string>()(k.relationshipArguments[1]) << 1)) >> 1)
               ^ (hash<int>()(k.relationshipArgumentTypes[0]) << 1) >> 1)
			   ^ (hash<int>()(k.relationshipArgumentTypes[1]) <<1 ) >> 1)
			   ^ (hash<int>()(k.relationshipType) <<1 );
	  
    }
  };

}